home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / Synthesizer Source / Synthesizer Folder / OscBankPlayer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  33.7 KB  |  979 lines  |  [TEXT/KAHL]

  1. /* OscBankPlayer.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Synthesizer:  Digital Music Synthesis on General Purpose Computers     */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define ShowMeFrozenNoteRec
  31. #define ShowMe_NoteObjectRec
  32. #include "OscBankPlayer.h"
  33. #include "LFOGenerator.h"
  34. #include "IncrementalParameterUpdator.h"
  35. #include "LFOSpecifier.h"
  36. #include "LFOListSpecifier.h"
  37. #include "Memory.h"
  38. #include "Array.h"
  39. #include "OscillatorListSpecifier.h"
  40. #include "OscillatorSpecifier.h"
  41. #include "InstrumentStructure.h"
  42. #include "GenInstrTopology.h"
  43. #include "SampleOscControl.h"
  44. #include "WaveTableOscControl.h"
  45. #include "ModulationOscControl.h"
  46. #include "DeterminedNoteStructure.h"
  47. #include "NoteObject.h"
  48. #include "FloatingPoint.h"
  49. #include "Frequency.h"
  50. #include "ErrorDaemon.h"
  51.  
  52.  
  53. typedef struct
  54.     {
  55.         /* this is the reference to the template object */
  56.         void*                                        TemplateReference;
  57.  
  58.         /* perform one envelope update cycle */
  59.         void                                        (*UpdateEnvelopes)(void* State);
  60.         /* dispose of the state record */
  61.         void                                        (*DisposeState)(void* State);
  62.         /* dispose of the information template */
  63.         void                                        (*DisposeTemplate)(void* Template);
  64.         /* create a new state object. */
  65.         void*                                        (*NewState)(void* Template,
  66.                                                             float FreqForMultisampling, float Accent1, float Accent2,
  67.                                                             float Accent3, float Accent4, float Loudness, float HurryUp,
  68.                                                             long* PreOriginTimeOut, float StereoPosition,
  69.                                                             float InitialFrequency, float LoudnessLFOAmplitudeScaling,
  70.                                                             float LoudnessLFOFrequencyScaling, MyBoolean DoingModulation);
  71.         /* fix up pre-origin time for the state object */
  72.         void                                        (*FixUpStatePreOrigin)(void* State, long ActualPreOrigin);
  73.         /* set a new frequency for a state object.  used for portamento */
  74.         /* and modulation of frequency (vibrato) */
  75.         void                                        (*StateNewFrequency)(void* State, float NewFrequencyHertz);
  76.         /* send a key-up signal to one of the oscillators */
  77.         void                                        (*KeyUpSustain1)(void* State);
  78.         void                                        (*KeyUpSustain2)(void* State);
  79.         void                                        (*KeyUpSustain3)(void* State);
  80.         /* restart a oscillator.  this is used for tie continuations */
  81.         void                                        (*RestartState)(void* State, float NewFreqMultisampling,
  82.                                                             float NewAccent1, float NewAccent2, float NewAccent3,
  83.                                                             float NewAccent4, float NewLoudness, float NewHurryUp,
  84.                                                             MyBoolean RetriggerEnvelopes, float NewStereoPosition,
  85.                                                             float NewInitialFrequency,
  86.                                                             float NewLoudnessLFOAmplitudeScaling,
  87.                                                             float NewLoudnessLFOFrequencyScaling);
  88.         /* generate a sequence of samples (called for each envelope clock) */
  89.         void                                        (*GenSamples)(void* State, long SampleCount,
  90.                                                             largefixedsigned* RawBuffer);
  91.         /* find out if the oscillator has finished yet */
  92.         MyBoolean                                (*IsItFinished)(void* State);
  93.     } OscBankVectorRec;
  94.  
  95.  
  96. struct OscBankTemplateRec
  97.     {
  98.         /* general parameters */
  99.         MyBoolean                                StereoOutput;
  100.         float                                        OverallVolumeScalingFactor;
  101.         long                                        SamplingRate;
  102.         float                                        EnvelopeUpdateRate;
  103.         MyBoolean                                TimeInterpolation;
  104.         MyBoolean                                WaveInterpolation;
  105.  
  106.         /* parameter updator for track (so we can set up individual notes properly) */
  107.         IncrParamUpdateRec*            ParamUpdator;
  108.  
  109.         /* template for the pitch displacement LFO */
  110.         LFOListSpecRec*                    PitchLFOTemplate;
  111.  
  112.         /* instrument overall loudness */
  113.         float                                        InstrOverallLoudness;
  114.  
  115.         /* list of template records describing each oscillator */
  116.         OscBankVectorRec*                TemplateArray;
  117.         /* this is the number of oscillators in the array */
  118.         long                                        NumOscillatorsInBank;
  119.     };
  120.  
  121.  
  122. typedef struct OscStateRec
  123.     {
  124.         /* this is a reference to the state object for this oscillator */
  125.         void*                                        StateReference;
  126.  
  127.         /* copy of the routine vectors */
  128.         OscBankVectorRec                Template;
  129.  
  130.         /* next oscillator in the list */
  131.         struct OscStateRec*            Next;
  132.     } OscStateRec;
  133.  
  134.  
  135. struct OscStateBankRec
  136.     {
  137.         /* what are we derived from */
  138.         OscBankTemplateRec*            BankTemplate;
  139.  
  140.         /* list of oscillators that this oscillator bank is comprised of */
  141.         OscStateRec*                        OscillatorList;
  142.  
  143.         /* this calculates the differential values for periodic pitch displacements */
  144.         LFOGenRec*                            PitchLFO;
  145.  
  146.         /* if this object ties to a note, then this is the note to tie to.  this is */
  147.         /* used for finding existing oscillators for tie continuations. */
  148.         struct NoteObjectRec*        TieToNote;
  149.  
  150.         /* portamento control parameters */
  151.         long                                        PortamentoCounter; /* 0 = done */
  152.         long                                        TotalPortamentoTicks;
  153.         float                                        InitialFrequency;
  154.         float                                        FinalFrequency;
  155.         float                                        CurrentFrequency;
  156.         /* True = portamento linear to Hertz; False = portamento linear to half-steps */
  157.         MyBoolean                                PortamentoHertz;
  158.         MyBoolean                                PitchLFOHertz;
  159.  
  160.         /* various counters (in terms of envelope ticks) */
  161.         /* negative = expired */
  162.         long                                        Release1Countdown;
  163.         long                                        Release2Countdown;
  164.         long                                        Release3Countdown;
  165.         long                                        PitchLFOStartCountdown;
  166.  
  167.         /* next oscillator bank in the list */
  168.         struct OscStateBankRec*    Next;
  169.     };
  170.  
  171.  
  172. static OscStateRec*                            StateFreeList = NIL;
  173. static OscStateBankRec*                    StateBankFreeList = NIL;
  174.  
  175.  
  176. /* flush all cached oscillator state bank records */
  177. void                                    FlushCachedOscStateBankRecords(void)
  178.     {
  179.         while (StateBankFreeList != NIL)
  180.             {
  181.                 OscStateBankRec*        Temp;
  182.  
  183.                 Temp = StateBankFreeList;
  184.                 StateBankFreeList = StateBankFreeList->Next;
  185.                 ReleasePtr((char*)Temp);
  186.             }
  187.  
  188.         while (StateFreeList != NIL)
  189.             {
  190.                 OscStateRec*                Temp;
  191.  
  192.                 Temp = StateFreeList;
  193.                 StateFreeList = StateFreeList->Next;
  194.                 ReleasePtr((char*)Temp);
  195.             }
  196.     }
  197.  
  198.  
  199. #if DEBUG
  200. static void                    ValidateOscState(OscStateRec* State)
  201.     {
  202.         OscStateRec*            Scan;
  203.  
  204.         CheckPtrExistence(State);
  205.         Scan = StateFreeList;
  206.         while (Scan != NIL)
  207.             {
  208.                 if (Scan == State)
  209.                     {
  210.                         PRERR(ForceAbort,"ValidateOscState:  state object is on free list");
  211.                     }
  212.                 Scan = Scan->Next;
  213.             }
  214.     }
  215. #else
  216. #define ValidateOscState(x) ((void)0)
  217. #endif
  218.  
  219.  
  220. #if DEBUG
  221. static void                    ValidateOscStateBank(OscStateBankRec* StateBank)
  222.     {
  223.         OscStateBankRec*    Scan;
  224.  
  225.         CheckPtrExistence(StateBank);
  226.         Scan = StateBankFreeList;
  227.         while (Scan != NIL)
  228.             {
  229.                 if (Scan == StateBank)
  230.                     {
  231.                         PRERR(ForceAbort,"ValidateOscStateBank:  state bank object is on free list");
  232.                     }
  233.                 Scan = Scan->Next;
  234.             }
  235.     }
  236. #else
  237. #define ValidateOscStateBank(x) ((void)0)
  238. #endif
  239.  
  240.  
  241. /* construct an oscillator bank template record.  various parameters are passed in */
  242. /* which are needed for synthesis.  ParameterUpdator is the parameter information */
  243. /* record for the whole track of which this is a part. */
  244. OscBankTemplateRec*        NewOscBankTemplate(struct InstrumentRec* InstrumentDefinition,
  245.                                                 MyBoolean StereoFlag, LargeBCDType OverallVolumeScalingReciprocal,
  246.                                                 long SamplingRate, float EnvelopeRate, MyBoolean TimeInterp,
  247.                                                 MyBoolean WaveInterp, struct IncrParamUpdateRec* ParameterUpdator,
  248.                                                 ErrorDaemonRec* ErrorDaemon)
  249.     {
  250.         OscBankTemplateRec*    Template;
  251.         ArrayRec*                        TwoDOscList;
  252.         OscillatorListRec*    OscillatorListObject;
  253.         OscillatorRec**            OscillatorVector;
  254.         long                                Scan;
  255.  
  256.         CheckPtrExistence(InstrumentDefinition);
  257.         CheckPtrExistence(ParameterUpdator);
  258.         CheckPtrExistence(ErrorDaemon);
  259.  
  260.         Template = (OscBankTemplateRec*)AllocPtrCanFail(sizeof(OscBankTemplateRec),
  261.             "OscBankTemplateRec");
  262.         if (Template == NIL)
  263.             {
  264.              FailurePoint1:
  265.                 return NIL;
  266.             }
  267.  
  268.         /* the oscillator bank template contains all of the information needed for */
  269.         /* constructing oscillators as notes are to be executed. */
  270.         /* number of oscillators in a bank. */
  271.         OscillatorListObject = GetInstrumentOscillatorList(InstrumentDefinition);
  272.         OscillatorVector = (OscillatorRec**)AllocPtrCanFail(sizeof(OscillatorRec*)
  273.             * GetOscillatorListLength(OscillatorListObject),"OscillatorRec[]");
  274.         if (OscillatorVector == NIL)
  275.             {
  276.              FailurePoint2:
  277.                 ReleasePtr((char*)Template);
  278.                 goto FailurePoint1;
  279.             }
  280.         for (Scan = 0; Scan < GetOscillatorListLength(OscillatorListObject); Scan += 1)
  281.             {
  282.                 PRNGCHK(OscillatorVector,&(OscillatorVector[Scan]),sizeof(OscillatorVector[Scan]));
  283.                 OscillatorVector[Scan] = GetOscillatorFromList(OscillatorListObject,Scan);
  284.             }
  285.         TwoDOscList = BuildOscillatorLists(OscillatorVector,
  286.             GetOscillatorListLength(OscillatorListObject));
  287.         if (TwoDOscList == NIL)
  288.             {
  289.              FailurePoint3:
  290.                 ReleasePtr((char*)OscillatorVector);
  291.                 goto FailurePoint2;
  292.             }
  293.  
  294.         /* get LFO information */
  295.         Template->PitchLFOTemplate = GetInstrumentFrequencyLFOList(InstrumentDefinition);
  296.  
  297.         /* vector containing templates for all of the oscillators */
  298.         Template->TemplateArray = (OscBankVectorRec*)AllocPtrCanFail(
  299.             sizeof(OscBankVectorRec) * ArrayGetLength(TwoDOscList),
  300.             "OscBankVectorRec");
  301.         if (Template->TemplateArray == NIL)
  302.             {
  303.              FailurePoint4:
  304.                 for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  305.                     {
  306.                         DisposeArray((ArrayRec*)ArrayGetElement(TwoDOscList,Scan));
  307.                     }
  308.                 DisposeArray(TwoDOscList);
  309.                 goto FailurePoint3;
  310.             }
  311.  
  312.         Template->NumOscillatorsInBank = 0;
  313.         for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  314.             {
  315.                 ArrayRec*                    OneOscArray;
  316.  
  317.                 OneOscArray = (ArrayRec*)ArrayGetElement(TwoDOscList,Scan);
  318.                 CheckPtrExistence(OneOscArray);
  319.                 if ((ArrayGetLength(OneOscArray) == 1) && (GetModulationSpecNumEntries(
  320.                     OscillatorGetModulatorInputList((OscillatorRec*)ArrayGetElement(
  321.                     OneOscArray,0))) == 0))
  322.                     {
  323.                         OscillatorRec*        Osc;
  324.  
  325.                         Osc = (OscillatorRec*)ArrayGetElement(OneOscArray,0);
  326.                         CheckPtrExistence(Osc);
  327.                         switch (OscillatorGetWhatKindItIs(Osc))
  328.                             {
  329.                                 default:
  330.                                     EXECUTE(PRERR(ForceAbort,"NewOscBankTemplate:  bad oscillator type"));
  331.                                     break;
  332.                                 case eOscillatorSampled:
  333.                                     PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  334.                                         sizeof(Template->TemplateArray[Scan]));
  335.                                     Template->TemplateArray[Scan].TemplateReference
  336.                                         = NewSampleTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  337.                                         TimeInterp,WaveInterp,ErrorDaemon);
  338.                                     if (Template->TemplateArray[Scan].TemplateReference == NIL)
  339.                                         {
  340.                                          FailurePoint5:
  341.                                             for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  342.                                                 {
  343.                                                     (*Template->TemplateArray[Scan]
  344.                                                         .DisposeTemplate)(Template->TemplateArray[
  345.                                                         Scan].TemplateReference);
  346.                                                 }
  347.                                             goto FailurePoint4;
  348.                                         }
  349.                                     Template->TemplateArray[Scan].UpdateEnvelopes
  350.                                         = (void (*)(void*))&UpdateSampleEnvelopes;
  351.                                     Template->TemplateArray[Scan].DisposeState
  352.                                         = (void (*)(void*))&DisposeSampleState;
  353.                                     Template->TemplateArray[Scan].DisposeTemplate
  354.                                         = (void (*)(void*))&DisposeSampleTemplate;
  355.                                     Template->TemplateArray[Scan].NewState
  356.                                         = (void* (*)(void*,float,float,float,float,float,
  357.                                         float,float,long*,float,float,float,float,MyBoolean))&NewSampleState;
  358.                                     Template->TemplateArray[Scan].FixUpStatePreOrigin
  359.                                         = (void (*)(void*,long))&FixUpSampleStatePreOrigin;
  360.                                     Template->TemplateArray[Scan].StateNewFrequency
  361.                                         = (void (*)(void*,float))&SampleStateNewFrequency;
  362.                                     Template->TemplateArray[Scan].KeyUpSustain1
  363.                                         = (void (*)(void*))&SampleKeyUpSustain1;
  364.                                     Template->TemplateArray[Scan].KeyUpSustain2
  365.                                         = (void (*)(void*))&SampleKeyUpSustain2;
  366.                                     Template->TemplateArray[Scan].KeyUpSustain3
  367.                                         = (void (*)(void*))&SampleKeyUpSustain3;
  368.                                     Template->TemplateArray[Scan].RestartState
  369.                                         = (void (*)(void*,float,float,float,float,float,float,float,
  370.                                         MyBoolean,float,float,float,float))&RestartSampleState;
  371.                                     Template->TemplateArray[Scan].GenSamples
  372.                                         = (void (*)(void*,long,largefixedsigned*))&SampleGenSamples;
  373.                                     Template->TemplateArray[Scan].IsItFinished
  374.                                         = (MyBoolean (*)(void*))&SampleIsItFinished;
  375.                                     break;
  376.                                 case eOscillatorWaveTable:
  377.                                     PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  378.                                         sizeof(Template->TemplateArray[Scan]));
  379.                                     Template->TemplateArray[Scan].TemplateReference
  380.                                         = NewWaveTableTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  381.                                         TimeInterp,WaveInterp,ErrorDaemon);
  382.                                     if (Template->TemplateArray[Scan].TemplateReference == NIL)
  383.                                         {
  384.                                             goto FailurePoint5;
  385.                                         }
  386.                                     Template->TemplateArray[Scan].UpdateEnvelopes
  387.                                         = (void (*)(void*))&UpdateWaveTableEnvelopes;
  388.                                     Template->TemplateArray[Scan].DisposeState
  389.                                         = (void (*)(void*))&DisposeWaveTableState;
  390.                                     Template->TemplateArray[Scan].DisposeTemplate
  391.                                         = (void (*)(void*))&DisposeWaveTableTemplate;
  392.                                     Template->TemplateArray[Scan].NewState
  393.                                         = (void* (*)(void*,float,float,float,float,float,
  394.                                         float,float,long*,float,float,float,float,MyBoolean))&NewWaveTableState;
  395.                                     Template->TemplateArray[Scan].FixUpStatePreOrigin
  396.                                         = (void (*)(void*,long))&FixUpWaveTableStatePreOrigin;
  397.                                     Template->TemplateArray[Scan].StateNewFrequency
  398.                                         = (void (*)(void*,float))&WaveTableStateNewFrequency;
  399.                                     Template->TemplateArray[Scan].KeyUpSustain1
  400.                                         = (void (*)(void*))&WaveTableKeyUpSustain1;
  401.                                     Template->TemplateArray[Scan].KeyUpSustain2
  402.                                         = (void (*)(void*))&WaveTableKeyUpSustain2;
  403.                                     Template->TemplateArray[Scan].KeyUpSustain3
  404.                                         = (void (*)(void*))&WaveTableKeyUpSustain3;
  405.                                     Template->TemplateArray[Scan].RestartState
  406.                                         = (void (*)(void*,float,float,float,float,float,float,float,
  407.                                         MyBoolean,float,float,float,float))&RestartWaveTableState;
  408.                                     Template->TemplateArray[Scan].GenSamples
  409.                                         = (void (*)(void*,long,largefixedsigned*))&WaveTableGenSamples;
  410.                                     Template->TemplateArray[Scan].IsItFinished
  411.                                         = (MyBoolean (*)(void*))&WaveTableIsItFinished;
  412.                                     break;
  413.                             }
  414.                     }
  415.                  else
  416.                     {
  417.                         PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  418.                             sizeof(Template->TemplateArray[Scan]));
  419.                         Template->TemplateArray[Scan].TemplateReference
  420.                             = NewModOscTemplate(OneOscArray,EnvelopeRate,SamplingRate,StereoFlag,
  421.                             TimeInterp,WaveInterp,ErrorDaemon);
  422.                         if (Template->TemplateArray[Scan].TemplateReference == NIL)
  423.                             {
  424.                                 goto FailurePoint5;
  425.                             }
  426.                         Template->TemplateArray[Scan].UpdateEnvelopes
  427.                             = (void (*)(void*))&UpdateModOscEnvelopes;
  428.                         Template->TemplateArray[Scan].DisposeState
  429.                             = (void (*)(void*))&DisposeModOscState;
  430.                         Template->TemplateArray[Scan].DisposeTemplate
  431.                             = (void (*)(void*))&DisposeModOscTemplate;
  432.                         Template->TemplateArray[Scan].NewState
  433.                             = (void* (*)(void*,float,float,float,float,float,
  434.                             float,float,long*,float,float,float,float,MyBoolean))&NewModOscState;
  435.                         Template->TemplateArray[Scan].FixUpStatePreOrigin
  436.                             = (void (*)(void*,long))&FixUpModOscStatePreOrigin;
  437.                         Template->TemplateArray[Scan].StateNewFrequency
  438.                             = (void (*)(void*,float))&ModOscStateNewFrequency;
  439.                         Template->TemplateArray[Scan].KeyUpSustain1
  440.                             = (void (*)(void*))&ModOscKeyUpSustain1;
  441.                         Template->TemplateArray[Scan].KeyUpSustain2
  442.                             = (void (*)(void*))&ModOscKeyUpSustain2;
  443.                         Template->TemplateArray[Scan].KeyUpSustain3
  444.                             = (void (*)(void*))&ModOscKeyUpSustain3;
  445.                         Template->TemplateArray[Scan].RestartState
  446.                             = (void (*)(void*,float,float,float,float,float,float,float,
  447.                             MyBoolean,float,float,float,float))&RestartModOscState;
  448.                         Template->TemplateArray[Scan].GenSamples
  449.                             = (void (*)(void*,long,largefixedsigned*))&ModOscGenSamples;
  450.                         Template->TemplateArray[Scan].IsItFinished
  451.                             = (MyBoolean (*)(void*))&ModOscIsItFinished;
  452.                     }
  453.                 Template->NumOscillatorsInBank += 1;
  454.             }
  455.  
  456.         /* playback control parameters */
  457.         Template->StereoOutput = StereoFlag;
  458.         Template->OverallVolumeScalingFactor = 1.0 / LargeBCD2Single(OverallVolumeScalingReciprocal);
  459.         Template->SamplingRate = SamplingRate;
  460.         Template->EnvelopeUpdateRate = EnvelopeRate;
  461.         Template->TimeInterpolation = TimeInterp;
  462.         Template->WaveInterpolation = WaveInterp;
  463.  
  464.         Template->ParamUpdator = ParameterUpdator;
  465.  
  466.         Template->InstrOverallLoudness = GetInstrumentOverallLoudness(InstrumentDefinition);
  467.  
  468.         /* clean up the mess */
  469.         for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  470.             {
  471.                 DisposeArray((ArrayRec*)ArrayGetElement(TwoDOscList,Scan));
  472.             }
  473.         DisposeArray(TwoDOscList);
  474.         ReleasePtr((char*)OscillatorVector);
  475.  
  476.         return Template;
  477.     }
  478.  
  479.  
  480. /* dispose of the template */
  481. void                                    DisposeOscBankTemplate(OscBankTemplateRec* Template)
  482.     {
  483.         long                                Scan;
  484.  
  485.         CheckPtrExistence(Template);
  486.  
  487.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  488.             {
  489.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  490.                     sizeof(Template->TemplateArray[Scan]));
  491.                 (*Template->TemplateArray[Scan].DisposeTemplate)(Template->
  492.                     TemplateArray[Scan].TemplateReference);
  493.             }
  494.         ReleasePtr((char*)Template->TemplateArray);
  495.  
  496.         ReleasePtr((char*)Template);
  497.     }
  498.  
  499.  
  500. /* construct a new oscillator bank state object based on the note.  the note is */
  501. /* assumed to start "now" in terms of the parameters in the ParameterUpdator.  */
  502. /* the ScanningGapWidth is the number of envelope clock ticks in the current scanning */
  503. /* gap.  this is used to determine how far later than "now" in terms of the back */
  504. /* edge of the scanning gap (different from above) the osc bank should start playing. */
  505. /* *WhenToStartPlayingOut returns the number of envelope ticks after the back edge */
  506. /* of the scanning gap that the note should be started. */
  507. /*     <already played>       |    <scanning gap>     |    <not yet analyzed> */
  508. /*   time ---->    time ---->    time ---->    time ---->    time ---->   time ----> */
  509. /*                            ^A                      ^B     */
  510. /* point A is the back edge of the scanning gap.  as this edge moves forward in time, */
  511. /*   oscillator bank state objects are removed from the queue and playback is commenced */
  512. /*   for them. */
  513. /* point B is the front edge of the scanning gap.  as this edge moves forward in time, */
  514. /*   notes are extracted from the track and state bank objects are created for them. */
  515. /*   ParameterUpdator always reflects parameters at this point in time. */
  516. OscStateBankRec*            NewOscBankState(OscBankTemplateRec* Template,
  517.                                                 long* WhenToStartPlayingOut, struct NoteObjectRec* Note,
  518.                                                 float EnvelopeTicksPerDurationTick)
  519.     {
  520.         OscStateBankRec*        State;
  521.         long                                Scan;
  522.         FrozenNoteRec*            FrozenNote;
  523.         long                                StartPointAdjust;
  524.         long                                MaxOscillatorPreOriginTime;
  525.         OscStateRec*                OneState;
  526.         long                                ThisPreOriginTime;
  527.  
  528.         CheckPtrExistence(Template);
  529.         CheckPtrExistence(Note);
  530.  
  531.         if (StateBankFreeList != NIL)
  532.             {
  533.                 State = StateBankFreeList;
  534.                 StateBankFreeList = StateBankFreeList->Next;
  535.             }
  536.          else
  537.             {
  538.                 State = (OscStateBankRec*)AllocPtrCanFail(sizeof(OscStateBankRec),"OscStateBankRec");
  539.                 if (State == NIL)
  540.                     {
  541.                      FailurePoint1:
  542.                         return NIL;
  543.                     }
  544.             }
  545.         EXECUTE(State->Next = (OscStateBankRec*)0x81818181;)
  546.  
  547.         State->BankTemplate = Template;
  548.  
  549.         /* freeze the parameters */
  550.         FrozenNote = FixNoteParameters(Template->ParamUpdator,Note,&StartPointAdjust,
  551.             Template->OverallVolumeScalingFactor,EnvelopeTicksPerDurationTick);
  552.         if (FrozenNote == NIL)
  553.             {
  554.              FailurePoint2:
  555.                 State->Next = StateBankFreeList;
  556.                 StateBankFreeList = State;
  557.                 goto FailurePoint1;
  558.             }
  559.  
  560.         /* list of oscillators that this oscillator bank is comprised of */
  561.         State->OscillatorList = NIL;
  562.         MaxOscillatorPreOriginTime = 0;
  563.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  564.             {
  565.                 /* allocate the new record */
  566.                 if (StateFreeList != NIL)
  567.                     {
  568.                         OneState = StateFreeList;
  569.                         StateFreeList = StateFreeList->Next;
  570.                     }
  571.                  else
  572.                     {
  573.                         OneState = (OscStateRec*)AllocPtrCanFail(sizeof(OscStateRec),"OscStateRec");
  574.                         if (OneState == NIL)
  575.                             {
  576.                              FailurePoint3:
  577.                                 while (State->OscillatorList != NIL)
  578.                                     {
  579.                                         /* delink object */
  580.                                         OneState = State->OscillatorList;
  581.                                         State->OscillatorList = State->OscillatorList->Next;
  582.                                         /* dispose members */
  583.                                         (*OneState->Template.DisposeState)(OneState->StateReference);
  584.                                         /* stick on free list */
  585.                                         OneState->Next = StateFreeList;
  586.                                         StateFreeList = OneState;
  587.                                     }
  588.                                 goto FailurePoint2;
  589.                             }
  590.                     }
  591.  
  592.                 /* copy over the function vectors */
  593.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  594.                     sizeof(Template->TemplateArray[Scan]));
  595.                 OneState->Template = Template->TemplateArray[Scan];
  596.  
  597.                 /* create the oscillator */
  598.                 OneState->StateReference = (OneState->Template.NewState)(
  599.                     OneState->Template.TemplateReference,FrozenNote->MultisampleFrequency,
  600.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  601.                     FrozenNote->LoudnessAdjust * Template->InstrOverallLoudness,
  602.                     FrozenNote->HurryUpFactor,&ThisPreOriginTime,FrozenNote->StereoPosition,
  603.                     FrozenNote->NominalFrequency,/*LoudnessLFOAmplitudeScaling?*/1,
  604.                     /*LoudnessLFOFrequencyScaling?*/1,False);
  605.                 if (OneState->StateReference == NIL)
  606.                     {
  607.                      FailurePoint3a:
  608.                         OneState->Next = StateFreeList;
  609.                         StateFreeList = OneState;
  610.                         goto FailurePoint3;
  611.                     }
  612.  
  613.                 if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  614.                     {
  615.                         MaxOscillatorPreOriginTime = ThisPreOriginTime;
  616.                     }
  617.  
  618.                 /* link it in */
  619.                 OneState->Next = State->OscillatorList;
  620.                 State->OscillatorList = OneState;
  621.             }
  622.  
  623.         /* this calculates the differential values for periodic pitch displacements */
  624.         State->PitchLFOHertz = FrozenNote->PitchDisplacementDepthInHertz;
  625.         if (!State->PitchLFOHertz)
  626.             {
  627.                 /* half steps */
  628.                 State->PitchLFO = NewLFOGenerator(Template->PitchLFOTemplate,&ThisPreOriginTime,
  629.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  630.                     FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  631.                     Template->EnvelopeUpdateRate,FrozenNote->PitchDisplacementDepthLimit / 12,
  632.                     FrozenNote->PitchDisplacementRateLimit,eLFOArithGeometric,1,
  633.                     FrozenNote->MultisampleFrequency);
  634.             }
  635.          else
  636.             {
  637.                 State->PitchLFO = NewLFOGenerator(Template->PitchLFOTemplate,&ThisPreOriginTime,
  638.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  639.                     FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  640.                     Template->EnvelopeUpdateRate,FrozenNote->PitchDisplacementDepthLimit,
  641.                     FrozenNote->PitchDisplacementRateLimit,eLFOArithAdditive,1,
  642.                     FrozenNote->MultisampleFrequency);
  643.             }
  644.         if (State->PitchLFO == NIL)
  645.             {
  646.              FailurePoint4:
  647.                 goto FailurePoint3;
  648.             }
  649.         if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  650.             {
  651.                 MaxOscillatorPreOriginTime = ThisPreOriginTime;
  652.             }
  653.  
  654.         /* if this object ties to a note, then this is the note to tie to.  this is */
  655.         /* used for finding existing oscillators for tie continuations. */
  656.         State->TieToNote = Note->a.Note.Tie;
  657.  
  658.         /* portamento control parameters */
  659.         State->PortamentoCounter = 0;
  660.         State->CurrentFrequency = FrozenNote->NominalFrequency;
  661.  
  662.         /* fix up pre-origin times */
  663.         OneState = State->OscillatorList;
  664.         while (OneState != NIL)
  665.             {
  666.                 (*OneState->Template.FixUpStatePreOrigin)(OneState->StateReference,
  667.                     MaxOscillatorPreOriginTime);
  668.                 OneState = OneState->Next;
  669.             }
  670.         LFOGeneratorFixEnvelopeOrigins(State->PitchLFO,MaxOscillatorPreOriginTime);
  671.  
  672.         /* various counters (in terms of envelope ticks) */
  673.         if (State->TieToNote == NIL)
  674.             {
  675.                 State->Release1Countdown = FrozenNote->ReleasePoint1
  676.                     + MaxOscillatorPreOriginTime;
  677.                 State->Release2Countdown = FrozenNote->ReleasePoint2
  678.                     + MaxOscillatorPreOriginTime;
  679.                 State->Release3Countdown = FrozenNote->ReleasePoint3
  680.                     + MaxOscillatorPreOriginTime;
  681.             }
  682.          else
  683.             {
  684.                 /* for ties, only honor releases from start */
  685.                 if (FrozenNote->Release1FromStart)
  686.                     {
  687.                         State->Release1Countdown = FrozenNote->ReleasePoint1
  688.                             + MaxOscillatorPreOriginTime;
  689.                     }
  690.                  else
  691.                     {
  692.                         State->Release1Countdown = -1;
  693.                     }
  694.                 if (FrozenNote->Release2FromStart)
  695.                     {
  696.                         State->Release2Countdown = FrozenNote->ReleasePoint2
  697.                             + MaxOscillatorPreOriginTime;
  698.                     }
  699.                  else
  700.                     {
  701.                         State->Release2Countdown = -1;
  702.                     }
  703.                 if (FrozenNote->Release3FromStart)
  704.                     {
  705.                         State->Release3Countdown = FrozenNote->ReleasePoint3
  706.                             + MaxOscillatorPreOriginTime;
  707.                     }
  708.                  else
  709.                     {
  710.                         State->Release3Countdown = -1;
  711.                     }
  712.             }
  713.         State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint
  714.             + MaxOscillatorPreOriginTime;
  715.  
  716.         /* clean up */
  717.         DisposeFrozenNote(FrozenNote);
  718.  
  719.         *WhenToStartPlayingOut = StartPointAdjust - MaxOscillatorPreOriginTime;
  720.  
  721.         return State;
  722.     }
  723.  
  724.  
  725. /* this is used for resetting a note for a tie */
  726. /* the FrozenNote object is NOT disposed */
  727. MyBoolean                            ResetOscBankState(OscStateBankRec* State,
  728.                                                 struct FrozenNoteRec* FrozenNote,
  729.                                                 float EnvelopeTicksPerDurationTick)
  730.     {
  731.         OscStateRec*                OneState;
  732.         MyBoolean                        RetriggerEnvelopes;
  733.  
  734.         CheckPtrExistence(State);
  735.         ValidateOscStateBank(State);
  736.         CheckPtrExistence(FrozenNote);
  737.  
  738.         RetriggerEnvelopes = ((FrozenNote->OriginalNote->Flags
  739.             & eRetriggerEnvelopesOnTieFlag) != 0);
  740.  
  741.         /* go through the oscillators and retrigger them */
  742.         OneState = State->OscillatorList;
  743.         while (OneState != NIL)
  744.             {
  745.                 (*OneState->Template.RestartState)(OneState->StateReference,
  746.                     FrozenNote->MultisampleFrequency,FrozenNote->Accent1,FrozenNote->Accent2,
  747.                     FrozenNote->Accent3,FrozenNote->Accent4,FrozenNote->LoudnessAdjust,
  748.                     FrozenNote->HurryUpFactor,RetriggerEnvelopes,FrozenNote->StereoPosition,
  749.                     FrozenNote->NominalFrequency,/*LoudnessLFOAmplitudeScaling?*/1,
  750.                     /*LoudnessLFOFrequencyScaling?*/1);
  751.                 OneState = OneState->Next;
  752.             }
  753.  
  754.         LFOGeneratorRetriggerFromOrigin(State->PitchLFO,FrozenNote->Accent1,
  755.             FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  756.             FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  757.             State->BankTemplate->EnvelopeUpdateRate,
  758.             FrozenNote->PitchDisplacementDepthLimit / 12,
  759.             FrozenNote->PitchDisplacementRateLimit,RetriggerEnvelopes);
  760.         State->PitchLFOHertz = FrozenNote->PitchDisplacementDepthInHertz;
  761.  
  762.         /* if this object ties to a note, then this is the note to tie to.  this is */
  763.         /* used for finding existing oscillators for tie continuations. */
  764.         State->TieToNote = FrozenNote->OriginalNote->a.Note.Tie;
  765.  
  766.         /* portamento control parameters */
  767.         if (FrozenNote->PortamentoDuration > 0)
  768.             {
  769.                 State->PortamentoCounter = FrozenNote->PortamentoDuration;
  770.                 State->TotalPortamentoTicks = FrozenNote->PortamentoDuration;
  771.                 State->InitialFrequency = State->CurrentFrequency; /* save current pitch */
  772.                 State->FinalFrequency = FrozenNote->NominalFrequency;
  773.                 State->PortamentoHertz = ((FrozenNote->OriginalNote->Flags
  774.                     & ePortamentoHertzNotHalfsteps) != 0);
  775.             }
  776.          else
  777.             {
  778.                 State->PortamentoCounter = 0;
  779.                 State->CurrentFrequency = FrozenNote->NominalFrequency;
  780.             }
  781.  
  782.         /* various counters (in terms of envelope ticks) */
  783.         if (State->TieToNote == NIL)
  784.             {
  785.                 State->Release1Countdown = FrozenNote->ReleasePoint1;
  786.                 State->Release2Countdown = FrozenNote->ReleasePoint2;
  787.                 State->Release3Countdown = FrozenNote->ReleasePoint3;
  788.             }
  789.          else
  790.             {
  791.                 /* for ties, only honor releases from start */
  792.                 if (FrozenNote->Release1FromStart)
  793.                     {
  794.                         State->Release1Countdown = FrozenNote->ReleasePoint1;
  795.                     }
  796.                  else
  797.                     {
  798.                         State->Release1Countdown = -1;
  799.                     }
  800.                 if (FrozenNote->Release2FromStart)
  801.                     {
  802.                         State->Release2Countdown = FrozenNote->ReleasePoint2;
  803.                     }
  804.                  else
  805.                     {
  806.                         State->Release2Countdown = -1;
  807.                     }
  808.                 if (FrozenNote->Release3FromStart)
  809.                     {
  810.                         State->Release3Countdown = FrozenNote->ReleasePoint3;
  811.                     }
  812.                  else
  813.                     {
  814.                         State->Release3Countdown = -1;
  815.                     }
  816.             }
  817.         if (RetriggerEnvelopes)
  818.             {
  819.                 State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint;
  820.             }
  821.          else
  822.             {
  823.                 State->PitchLFOStartCountdown = -1;
  824.             }
  825.  
  826.         return True;
  827.     }
  828.  
  829.  
  830. /* get rid of a state bank */
  831. void                                    DisposeOscStateBank(OscStateBankRec* State)
  832.     {
  833.         OscStateRec*                OneStateScan;
  834.  
  835.         CheckPtrExistence(State);
  836.         ValidateOscStateBank(State);
  837.  
  838.         OneStateScan = State->OscillatorList;
  839.         while (OneStateScan != NIL)
  840.             {
  841.                 OscStateRec*                Temp;
  842.  
  843.                 (*OneStateScan->Template.DisposeState)(OneStateScan->StateReference);
  844.                 Temp = OneStateScan;
  845.                 OneStateScan = OneStateScan->Next;
  846.                 Temp->Next = StateFreeList;
  847.                 StateFreeList = Temp;
  848.             }
  849.  
  850.         DisposeLFOGenerator(State->PitchLFO);
  851.  
  852.         State->Next = StateBankFreeList;
  853.         StateBankFreeList = State;
  854.     }
  855.  
  856.  
  857. /* get the reference to the note that this bank ties to.  NIL if it doesn't */
  858. struct NoteObjectRec*    GetOscStateTieTarget(OscStateBankRec* State)
  859.     {
  860.         CheckPtrExistence(State);
  861.         ValidateOscStateBank(State);
  862.  
  863.         return State->TieToNote;
  864.     }
  865.  
  866.  
  867. /* perform one envelope clock cycle on a state bank.  this returns True if the */
  868. /* state bank is done and should be retired.  (it will return false if it is a */
  869. /* tie source.) */
  870. MyBoolean                            UpdateOscStateBank(OscStateBankRec* State, long NumFrames,
  871.                                                 largefixedsigned* OutputData)
  872.     {
  873.         OscStateRec*                OneStateScan;
  874.         MyBoolean                        OscillatorsRunning;
  875.         float                                Frequency;
  876.  
  877.         CheckPtrExistence(State);
  878.         ValidateOscStateBank(State);
  879.  
  880.         if (State->Release1Countdown >= 0)
  881.             {
  882.                 State->Release1Countdown -= 1;
  883.                 if (State->Release1Countdown == 0)
  884.                     {
  885.                         OneStateScan = State->OscillatorList;
  886.                         while (OneStateScan != NIL)
  887.                             {
  888.                                 (*OneStateScan->Template.KeyUpSustain1)(OneStateScan->StateReference);
  889.                                 OneStateScan = OneStateScan->Next;
  890.                             }
  891.                         LFOGeneratorKeyUpSustain1(State->PitchLFO);
  892.                     }
  893.             }
  894.  
  895.         if (State->Release2Countdown >= 0)
  896.             {
  897.                 State->Release2Countdown -= 1;
  898.                 if (State->Release2Countdown == 0)
  899.                     {
  900.                         OneStateScan = State->OscillatorList;
  901.                         while (OneStateScan != NIL)
  902.                             {
  903.                                 (*OneStateScan->Template.KeyUpSustain2)(OneStateScan->StateReference);
  904.                                 OneStateScan = OneStateScan->Next;
  905.                             }
  906.                         LFOGeneratorKeyUpSustain2(State->PitchLFO);
  907.                     }
  908.             }
  909.  
  910.         if (State->Release3Countdown >= 0)
  911.             {
  912.                 State->Release3Countdown -= 1;
  913.                 if (State->Release3Countdown == 0)
  914.                     {
  915.                         OneStateScan = State->OscillatorList;
  916.                         while (OneStateScan != NIL)
  917.                             {
  918.                                 (*OneStateScan->Template.KeyUpSustain3)(OneStateScan->StateReference);
  919.                                 OneStateScan = OneStateScan->Next;
  920.                             }
  921.                         LFOGeneratorKeyUpSustain3(State->PitchLFO);
  922.                     }
  923.             }
  924.  
  925.         /* perform portamento */
  926.         if (State->PortamentoCounter > 0)
  927.             {
  928.                 /* decrement is done before interpolation so that the final frequency */
  929.                 /* will actually be reached. */
  930.                 State->PortamentoCounter -= 1;
  931.                 if (State->PortamentoHertz)
  932.                     {
  933.                         /* this transition is linear, so it's easy to compute */
  934.                         /* L+F(R-L) */
  935.                         State->CurrentFrequency = State->InitialFrequency
  936.                             + ((float)(State->TotalPortamentoTicks
  937.                             - State->PortamentoCounter) / State->TotalPortamentoTicks)
  938.                             * (State->FinalFrequency - State->InitialFrequency);
  939.                     }
  940.                  else
  941.                     {
  942.                         /* this transition is log-linear, so it's a bit messier */
  943.                         State->CurrentFrequency = State->InitialFrequency * (float)FEXP(
  944.                             ((float)(State->TotalPortamentoTicks - State->PortamentoCounter)
  945.                             / State->TotalPortamentoTicks)
  946.                             * (((float)FLN(State->FinalFrequency) / (float)LOG2)
  947.                             - ((float)FLN(State->InitialFrequency) / (float)LOG2)) * LOG2);
  948.                     }
  949.             }
  950.  
  951.         /* update the pitch LFO modulation & figure out what the current pitch is */
  952.         if (State->PitchLFOStartCountdown > 0)
  953.             {
  954.                 State->PitchLFOStartCountdown -= 1;
  955.                 Frequency = State->CurrentFrequency;
  956.             }
  957.          else
  958.             {
  959.                 /* do some pitch stuff */
  960.                 Frequency = FastFixed2Float(LFOGenUpdateCycle(State->PitchLFO,
  961.                     Double2FastFixed(State->CurrentFrequency)));
  962.             }
  963.  
  964.         /* perform a cycle of resampling */
  965.         OscillatorsRunning = False;
  966.         OneStateScan = State->OscillatorList;
  967.         while (OneStateScan != NIL)
  968.             {
  969.                 (*OneStateScan->Template.StateNewFrequency)(OneStateScan->StateReference,Frequency);
  970.                 (*OneStateScan->Template.UpdateEnvelopes)(OneStateScan->StateReference);
  971.                 (*OneStateScan->Template.GenSamples)(OneStateScan->StateReference,NumFrames,OutputData);
  972.                 OscillatorsRunning = OscillatorsRunning || !(*OneStateScan->Template
  973.                     .IsItFinished)(OneStateScan->StateReference);
  974.                 OneStateScan = OneStateScan->Next;
  975.             }
  976.  
  977.         return !OscillatorsRunning;
  978.     }
  979.